const fs = require("fs");
const uuid = require("uuid");
const path = require("path");
Buffer.prototype.split = function (sep) {
  sep = Buffer.isBuffer(sep) ? sep : Buffer.from(sep); //Buffer.from 只能放入字符串
  let offset = 0;
  let arr = [];
  let idx = 0;
  while (-1 != (idx = this.indexOf(sep, offset))) {
    arr.push(this.slice(offset, idx));
    offset = idx + sep.length;
  }
  arr.push(this.slice(offset));
  return arr;
};
module.exports = function multer(uploadDir) {
  return async function (ctx, next) {
    // 'multipart/form-data; boundary=----WebKitFormBoundaryDnStpAT3uQ31yHFa'
    let contentType = ctx.get("Content-Type");

    if (contentType.startsWith("multipart/form-data")) {
      let boundary = contentType.split("=")[1];
      // body 就是整个的数据
      let body = await new Promise((resolve, reject) => {
        let arr = [];
        ctx.req.on("data", function (chunk) {
          arr.push(chunk);
        });
        ctx.req.on("end", function () {
          resolve(Buffer.concat(arr));
        });
      });
      // buffer
      let lines = body.split("--" + boundary);
      lines = lines.slice(1, -1); // 有用的数据
      let finalObj = {};
      lines.forEach((line) => {
        let [header] = line.split(Buffer.from([0x0d, 0x0a, 0x0d, 0x0a]));
        header = header.toString();
        let key = header.match(/name="([^"]+)"/)[1];
        if (header.includes("filename")) {
          let originaFile = header.match(/filename="([^"]+)"/)[1];
          let fileContent = line.slice(header.length + 4, -2); // 文件内容
          const filename = uuid.v4();
          fs.writeFileSync(path.resolve(uploadDir, uuid.v4()), fileContent);
          ctx.request.file = {
            originaFile: originaFile,
            filename,
          };
          finalObj["file"] = ctx.request.file;
          // 文件
        } else {
          // 正常的字段
          let value = line.slice(header.length + 4, -2).toString(); // 去头去尾
          finalObj[key] = value;
        }
      });
      ctx.request.body = finalObj;
      return next();
    } else {
      return next();
    }
  };
};
